home *** CD-ROM | disk | FTP | other *** search
/ AOL File Library: 2,801 to 2,900 / aol-file-protocol-4400-2801-to-2900.zip / AOLDLs / C++ Files Library / SK (Sockects) 1.4.1 r2 / SK v1.4.1 r2.sit / SK 1.4.1 r2 / SK / SK Sources / SK_INET.cc < prev    next >
Text File  |  1994-06-13  |  22KB  |  972 lines

  1. /***************************************************************************
  2. * Copyright ⌐ 1992-1994 Matthias Neeracher and the Decision Systems Group
  3. * Permission is granted to anyone to use this software for any purpose on
  4. * any computer system, and to redistribute it freely, subject to the
  5. * following restrictions:
  6. * 1) The authors and the Decision Systems Group are not responsible for 
  7. *    the direct or indirect consequences of use of this software, no matter 
  8. *    how awful, even if they arise from defects in the software itself.
  9. *    This restriction applies to the use of this and any derived source code 
  10. *    and also to the use of all binary produced from this and any derived 
  11. *    source code.
  12. * 2) The origin and copyrights of this software must not be misrepresented, 
  13. *    either by explicit claim or by omission or alteration of copyright or
  14. *    authorship header information in this file or in any derived file.
  15. * 3) Altered or derived versions must be plainly marked as such, and must not
  16. *    be misrepresented as being the original software.
  17. * We encourage users of this software to provide feedback, bug fixes,
  18. * and enhancements to the authors for incorporation into future releases.
  19. *
  20. * ==========================================================================
  21. * FILE: SK_INET.cc
  22. * AUTHOR: Matthias Neeracher and Stephan Deibel
  23. * CREATION DATE: 12Aug92
  24. * VERSION: 13Jun94
  25. * DESCRIPTION: 
  26. *
  27. * General routines for TCP and UDP sockets
  28. * NOTES: 
  29. * 0) This code was derived from Matthias Neerarcher's GUSI 1.1.0 and
  30. *    the socket library written by Charlie Reiman (creiman@ncsa.uiuc.edu)
  31. *    and Tom Milligan (milligan@madhaus.utcs.utoronto.ca); Copyrights
  32. *    are subject to this origin.
  33. *
  34. * MODIFICATIONS: 
  35. * --------------------------------------------------------------------------
  36. * Date     Name      Description of modification
  37. * --------------------------------------------------------------------------
  38. * 16Aug92    MN       Split
  39. * 20Aug92    MN       Wrote most of the functions
  40. * 23Aug92    MN       CSK_INETSocket::Available()
  41. * 31Jan93    MN       Inetd support
  42. * 07Feb93    MN       New configuration technique
  43. * 13Jul93    SD       Port to THINK C++ 6.0
  44. * 21Jul93    SD       Subsetted to only TCP/UDP, applied DSG naming 
  45. *                    conventions and commenting guidelines, and
  46. *                    changed name to "SK" for clear distinction from
  47. *                    the GUSI code from which this was derived
  48. * 13Jun94   SD       Updated based on relevant changes to GUSI (through 1.4.1)
  49. */
  50.  
  51. #include "SK_INET_P.hh"
  52. #include <machine/endian.h>
  53. #include <AppleEvents.h>
  54.  
  55.  
  56. /**************************************************************************/ 
  57. /**************************************************************************/ 
  58. /* Constants */
  59.  
  60. #define SKk_Num_PBs    32
  61.  
  62.  
  63. /**************************************************************************/ 
  64. /**************************************************************************/ 
  65. /* Globals */
  66.  
  67. CSK_INETSocketDomain SKg_INETSockets;
  68.  
  69.  
  70. /**************************************************************************/ 
  71. /**************************************************************************/ 
  72. /* Utilities */
  73.  
  74.  
  75. /*************************************************************************** *
  76. * Miscellaneous type conversion functions */
  77.  
  78. unsigned long (htonl)(unsigned long h)
  79. {
  80.     return h;
  81. }
  82.  
  83. unsigned short    (htons)(unsigned short h)
  84. {
  85.     return h;
  86. }
  87.  
  88. unsigned long (ntohl)(unsigned long n)
  89. {
  90.     return n;
  91. }
  92.  
  93. unsigned short    (ntohs)(unsigned short n)
  94. {
  95.     return n;
  96. }
  97.  
  98.  
  99. /*************************************************************************** *
  100. * FUNCTION:
  101. *
  102. * SK_TCPError
  103. *
  104. * DESCRIPTION:
  105. *
  106. * Our resident MacTCP error expert.  Convert MacTCP err codes into Unix 
  107. * error codes.
  108. *
  109. * PARAMETERS:
  110. *
  111. * int            -- Mac TCP error code
  112. *
  113. * RETURNS:
  114. *
  115. * int            -- Unix error code
  116. *
  117. */
  118.  
  119. int SK_TCPError(int MacTCPerr)
  120. {
  121.     switch ( MacTCPerr ) {
  122.     case 0:
  123.         return 0;
  124.     case ipBadLapErr:
  125.     case ipBadCnfgErr:
  126.     case ipNoCnfgErr:
  127.     case ipLoadErr:
  128.     case ipBadAddr:
  129.         errno = ENXIO;            /* device not configured */    /* a cheap cop out */
  130.         break;
  131.     case connectionClosing:
  132.         errno = ESHUTDOWN;        /* Can't send after socket shutdown */
  133.         break;
  134.     case connectionExists:
  135.         errno = EISCONN;        /* Socket is already connected */
  136.         break;
  137.     case connectionTerminated:
  138.         errno = ENOTCONN;        /* Connection reset by peer */  /* one of many possible */
  139.         break;
  140.     case openFailed:
  141.         errno = ECONNREFUSED;    /* Connection refused */
  142.         break;
  143.     case duplicateSocket:        /* technically, duplicate port */
  144.         errno = EADDRINUSE;        /* Address already in use */
  145.         break;
  146.     case ipDestDeadErr:
  147.         errno = EHOSTDOWN;        /* Host is down */
  148.         break;
  149.     case ipRouteErr:
  150.         errno = EHOSTUNREACH;    /* No route to host */
  151.         break;
  152.     default:
  153.         errno = MacTCPerr > 0 ? MacTCPerr : EFAULT;        /* cop out; an internal err, unix err, or no err */
  154.         break;
  155.     }
  156.  
  157.     return -1;
  158. }
  159.  
  160.  
  161. /*************************************************************************** *
  162. * FUNCTION:
  163. *
  164. * SK_TCPPossession
  165. *
  166. * DESCRIPTION:
  167. *
  168. * INETD support / for TCP
  169. *
  170. * PARAMETERS:
  171. *
  172. * AppleEvent *        -- incoming message
  173. * AppleEvent *        -- unused reply
  174. * long                -- unused refin
  175. *
  176. * RETURNS:
  177. *
  178. * OSErr                -- Error return (0 = no error)
  179. *
  180. * NOTES:
  181. *
  182. * This is a pascal callable function because it is installed as a callback
  183. * used with the Macintosh toolbox Apple Event Manager.
  184. *
  185. */
  186.  
  187. pascal OSErr 
  188. SK_TCPPossession(AppleEvent* messagein, AppleEvent*, long)
  189. {
  190.     AEDesc streamDesc;
  191.     OSErr theErr;
  192.     CSK_TCPSocket *sock;
  193.  
  194.     if ((theErr = AEGetParamDesc(messagein, 'STRM', typeLongInteger, &streamDesc)) == noErr) {
  195.         HLock(streamDesc.dataHandle);
  196.         sock = new CSK_TCPSocket(*((StreamPtr*) *(streamDesc.dataHandle)));
  197.         HUnlock(streamDesc.dataHandle);
  198.         SKg_SocketTable.Possess(0, sock);
  199.         SKg_SocketTable.Possess(1, sock);
  200.         SKg_SocketTable.Possess(2, sock);
  201.         
  202.         theErr = AEDisposeDesc(&streamDesc);
  203.     }
  204.  
  205.     return theErr;
  206. }
  207.  
  208.  
  209. /*************************************************************************** *
  210. * FUNCTION:
  211. *
  212. * SK_TCPPossession
  213. *
  214. * DESCRIPTION:
  215. *
  216. * INETD support / for UDP
  217. *
  218. * PARAMETERS:
  219. *
  220. * AppleEvent *        -- incoming message
  221. * AppleEvent *        -- unused reply
  222. * long                -- unused ref_in
  223. *
  224. * RETURNS:
  225. *
  226. * OSErr                -- Error return (0 = no error)
  227. *
  228. * NOTES:
  229. *
  230. * This is a pascal callable function because it is installed as a callback
  231. * used with the Macintosh toolbox Apple Event Manager.
  232. *
  233. */
  234.  
  235. pascal OSErr 
  236. SK_UDPPossession(AppleEvent* messagein, AppleEvent*, long)
  237. {
  238.     AEDesc streamDesc;
  239.     OSErr theErr;
  240.     CSK_UDPSocket *sock;
  241.  
  242.     if ((theErr = AEGetParamDesc(messagein, 'STRM', typeLongInteger, &streamDesc)) == noErr) {
  243.         HLock(streamDesc.dataHandle);
  244.         sock = new CSK_UDPSocket(*((StreamPtr*) *(streamDesc.dataHandle)));
  245.         HUnlock(streamDesc.dataHandle);
  246.         SKg_SocketTable.Possess(0, sock);
  247.         SKg_SocketTable.Possess(1, sock);
  248.         SKg_SocketTable.Possess(2, sock);
  249.         
  250.         theErr = AEDisposeDesc(&streamDesc);
  251.     }
  252.  
  253.     return theErr;
  254. }
  255.  
  256.  
  257. /**************************************************************************/ 
  258. /**************************************************************************/ 
  259. /* CSK_INETSocket members */
  260.  
  261.  
  262. /*************************************************************************** *
  263. * FUNCTION:
  264. *
  265. * CSK_INETSocket::CSK_INETSocket
  266. *
  267. * DESCRIPTION:
  268. *
  269. * Constructor for this class
  270. *
  271. */
  272.  
  273. CSK_INETSocket::CSK_INETSocket()
  274.     : CSK_Socket()
  275. {
  276.     bzero(&fMySocketAddress, sizeof(struct sockaddr_in));
  277.     bzero(&fPeerSocketAddress, sizeof(struct sockaddr_in));
  278.     
  279.     fMySocketAddress.sin_family    = AF_INET;
  280.     fMySocketAddress.sin_len = sizeof(struct sockaddr_in);
  281.     fStatus    = SKk_STATUS_USED;
  282.     fNonBlocking = false;    
  283.      
  284.     SKg_INETSockets.OpenSocket();
  285. }
  286.  
  287.  
  288. /*************************************************************************** *
  289. * FUNCTION:
  290. *
  291. * CSK_INETSocket::CSK_INETSocket
  292. *
  293. * DESCRIPTION:
  294. *
  295. * Constructor for this class
  296. *
  297. * PARAMETERS:
  298. *
  299. * StreamPtr            -- Stream to use for this internet socket
  300. *
  301. */
  302.  
  303. CSK_INETSocket::CSK_INETSocket(StreamPtr stream)
  304.     : CSK_Socket(), fStream(stream)
  305. {
  306.     fMySocketAddress.sin_family    = AF_INET;
  307.     fMySocketAddress.sin_len = sizeof(struct sockaddr_in);
  308.     fPeerSocketAddress.sin_family= AF_INET;
  309.     fPeerSocketAddress.sin_len = sizeof(struct sockaddr_in);
  310.     fStatus = SKk_STATUS_USED;
  311.     fSocketState = SKk_STATE_CONNECTED;
  312.     fNonBlocking = false;    
  313.      
  314.     SKg_INETSockets.OpenSocket();
  315. }
  316.  
  317.  
  318. /*************************************************************************** *
  319. * FUNCTION:
  320. *
  321. * CSK_INETSocket::~CSK_INETSocket
  322. *
  323. * DESCRIPTION:
  324. *
  325. * Destructor for this class
  326. *
  327. */
  328.  
  329. CSK_INETSocket::~CSK_INETSocket()
  330. {
  331.     SKg_INETSockets.CloseSocket();
  332. }
  333.  
  334.  
  335. /*************************************************************************** *
  336. * FUNCTION:
  337. *
  338. * CSK_INETSocket::Available
  339. *
  340. * DESCRIPTION:
  341. *
  342. * Compute the number of bytes available for reading on this socket.
  343. *
  344. * RETURNS:
  345. *
  346. * Number of bytes available, or 0 if none.
  347. *
  348. * NOTES:
  349. *
  350. * This member function must be overridden and implemented by descendents.
  351. *
  352. */
  353.  
  354. unsigned long CSK_INETSocket::Available()
  355. {
  356.     return 0;
  357. }
  358.  
  359.  
  360. /*************************************************************************** *
  361. * FUNCTION:
  362. *
  363. * CSK_INETSocket::bind
  364. *
  365. * DESCRIPTION:
  366. *
  367. * Requests that the name (ip address and port) pointed to by 
  368. * name be assigned to this socket.
  369. *
  370. * PARAMETERS:
  371. *
  372. * void *        -- The ip address to bind to
  373. * int            -- The length of the given ip address
  374. *
  375. * RETURNS:
  376. *
  377. * The return value is 0 on success or -1 if an error occurs,
  378. * in which case global variable errno is set to one of:
  379. *
  380. * EAFNOSUPPORT        The address family in name is not AF_INET.
  381. *        
  382. * EINVAL              The socket is already bound to an address.
  383. *        
  384. * EADDRNOTAVAIL       The specified address is  not  available
  385. *                       from the local machine. ie. the address
  386. *                      portion of name was not this machine's address.
  387. *
  388. * NOTES:
  389. *
  390. * MacTCP does not separate name binding and connection establishment.
  391. * Therefore the port number is not verified, just stored for later use.
  392. *
  393. * If a specific local port is not required, bind is optional in this
  394. * implementation.
  395. *
  396. */
  397.  
  398. int CSK_INETSocket::bind(void * addr, int namelen)
  399. {
  400.     struct sockaddr_in *name = (struct sockaddr_in *) addr;
  401.         
  402.     if (namelen < sizeof(struct sockaddr_in))
  403.         return SK_Error(EINVAL);
  404.  
  405.     if (name->sin_family != AF_INET)
  406.         return SK_Error(EAFNOSUPPORT);
  407.  
  408.     /* already bound */
  409.     if (fMySocketAddress.sin_port != 0)
  410.         return SK_Error(EINVAL);
  411.  
  412.     /* If client passed a local IP address, assure it is the right one */
  413.     if (name->sin_addr.s_addr != 0) 
  414.     {
  415.         struct GetAddrParamBlock pbr;
  416.         
  417.         pbr.ioCRefNum = SKg_INETSockets.Driver();
  418.         pbr.csCode = ipctlGetAddr;
  419.         
  420.         if (PBControlSync(ParmBlkPtr(&pbr)))
  421.             return SK_Error(ENETDOWN);
  422.         
  423.         if (name->sin_addr.s_addr != pbr.ourAddress)
  424.             return SK_Error(EADDRNOTAVAIL);
  425.     }
  426.  
  427.     /* NOTE: can't check a TCP port for EADDRINUSE just save the address 
  428.        and port away for connect or listen or... */
  429.     fMySocketAddress.sin_addr.s_addr = name->sin_addr.s_addr;
  430.     fMySocketAddress.sin_port = name->sin_port;
  431.     
  432.     return 0;
  433. }
  434.  
  435.  
  436. /*************************************************************************** *
  437. * FUNCTION:
  438. *
  439. * CSK_INETSocket::getsockname
  440. *
  441. * DESCRIPTION:
  442. *
  443. * Get the current name for this socket.
  444. *
  445. * PARAMETERS:
  446. *
  447. * void *            -- Pointer to memory for return value
  448. * int *                -- Pointer to memory for return value.  Should be initialized
  449. *                       the amount of space provided for name return
  450. *
  451. * RETURNS:
  452. *
  453. * The function return value indicates error status (0 = no error).  When it is
  454. * -1, a more specific return value is in the global errno.
  455. *
  456. * The name is returned in the given memory, truncated to available space
  457. * if necessary.  The length of the name (or truncated name) is returned
  458. * in the given int * parameter.
  459. *
  460. */
  461.  
  462. int CSK_INETSocket::getsockname(void *name, int *namelen)
  463. {
  464.     if (*namelen < 0)
  465.         return SK_Error(EINVAL);
  466.  
  467.     memcpy(name, &fMySocketAddress, *namelen = MIN(*namelen, sizeof(struct sockaddr_in)));
  468.     return 0;
  469. }
  470.  
  471.  
  472. /*************************************************************************** *
  473. * FUNCTION:
  474. *
  475. * CSK_INETSocket::getpeername
  476. *
  477. * DESCRIPTION:
  478. *
  479. * Returns the name of the (remote) peer connected to this socket
  480. *
  481. * PARAMETERS:
  482. *
  483. * void *            -- Pointer to memory for return value
  484. * int *                -- Pointer to memory for return value.  Should be initialized
  485. *                       the amount of space provided for name return
  486. *
  487. * RETURNS:
  488. *
  489. * The function return value indicates error status (0 = no error).  When it is
  490. * -1, a more specific return value is in the global errno.
  491. *
  492. * The name is returned in the given memory, truncated to available space
  493. * if necessary.  The length of the name (or truncated name) is returned
  494. * in the given int * parameter.
  495. *
  496. */
  497.  
  498. int CSK_INETSocket::getpeername(void *name, int *namelen)
  499. {
  500.     if (*namelen < 0)
  501.         return SK_Error(EINVAL);
  502.  
  503.     memcpy(name, &fPeerSocketAddress, *namelen = MIN(*namelen, sizeof(struct sockaddr_in)));
  504.     return 0;
  505. }
  506.  
  507.  
  508. /*************************************************************************** *
  509. * FUNCTION:
  510. *
  511. * CSK_INETSocket::shutdown
  512. *
  513. * DESCRIPTION:
  514. *
  515. * Closes all of part of a full-duplex connection on the given socket.
  516. *
  517. * PARAMETERS:
  518. *
  519. * int            -- How to close connection: If 0, further receives are
  520. *                   disabled; if 1, further sends are disabled; if 2
  521. *                   further sends and receives are disabled.
  522. *
  523. * RETURNS:
  524. *
  525. * The function return value indicates error status (0 = no error).  When it is
  526. * -1, a more specific return value is in the global errno.
  527. *
  528. */
  529.  
  530. int CSK_INETSocket::shutdown(int how)
  531. {
  532.     switch(how) {
  533.     case 0 : 
  534.         fStatus |= SKk_STATUS_NOREAD;
  535.         break;
  536.     case 1 : 
  537.         fStatus |= SKk_STATUS_NOWRITE;
  538.         break;
  539.     case 2 :
  540.         fStatus |= SKk_STATUS_NOREAD | SKk_STATUS_NOWRITE;
  541.         break;
  542.     default :
  543.         return SK_Error(EINVAL);
  544.     }
  545.     
  546.     return 0;
  547. }
  548.  
  549.  
  550. /*************************************************************************** *
  551. * FUNCTION:
  552. *
  553. * CSK_INETSocket::fcntl
  554. *
  555. * DESCRIPTION:
  556. *
  557. * Performs a given flag control operation on this socket.
  558. *
  559. * PARAMETERS:
  560. *
  561. * unsigned int            -- The command to execute, one of:
  562. *
  563. *     F_GETFL        returns the descriptor status flags. The only
  564. *                flag supported is FNDELAY for non-blocking i/o.
  565. *
  566. *     F_SETFL        sets descriptor status flags. The only
  567. *                 flag supported is FNDELAY for non-blocking i/o.
  568. *
  569. * int                    -- The argument for the command
  570. *
  571. * RETURNS:
  572. *
  573. * Upon successful completion, the value  returned  depends  on
  574. * cmd as follows:
  575.  
  576. *     F_GETFL   Value of flags.
  577. *    F_SETFL   0.
  578. *
  579. * On error, a value of -1  is returned and errno is set to indicate 
  580. * the error.
  581. *
  582. *     EBADF        s is not a valid open descriptor.
  583. *
  584. *    EMFILE        cmd is F_DUPFD and socket descriptor table is full.
  585. *
  586. *    EINVAL        cmd is F_DUPFD and arg  is  negative  or
  587. *                 greater   than   the  maximum  allowable
  588. *                number (see SK_getdtablesize).
  589. *
  590. */
  591.  
  592. int CSK_INETSocket::fcntl(unsigned int cmd, int arg)
  593. {
  594.     switch(cmd) {
  595.     
  596.     /* Get socket status.  This is like getsockopt().
  597.        Only supported descriptor status is FNDELAY. */
  598.     case F_GETFL : 
  599.         if (fNonBlocking)
  600.             return FNDELAY;
  601.         else
  602.             return 0;
  603.             
  604.     /* Set socket status.  This is like setsockopt().
  605.        Only supported descriptor status is FNDELAY. */
  606.     case F_SETFL : 
  607.         if (arg & FNDELAY)
  608.             fNonBlocking = true;
  609.         else
  610.             fNonBlocking = false;
  611.         
  612.         return 0;
  613.         
  614.     default:
  615.         return SK_Error(EOPNOTSUPP);
  616.     }
  617. }
  618.  
  619.  
  620. /*************************************************************************** *
  621. * FUNCTION:
  622. *
  623. * CSK_INETSocket::ioctl
  624. *
  625. * DESCRIPTION:
  626. *
  627. * Performs a requested io control action on this socket
  628. *
  629. * PARAMETERS:
  630. *
  631. * unsigned int                -- Requested control action
  632. * void *                    -- Pointer to arguments for given action
  633. *
  634. * RETURNS:
  635. *
  636. * The function return value indicates error status (0 = no error).  When it is
  637. * -1, a more specific return value is in the global errno.
  638. *
  639. */
  640.  
  641. int CSK_INETSocket::ioctl(unsigned int request, void *argp)
  642. {
  643.     struct ifreq *    ifr;
  644.     int                size;
  645.     
  646.     /* Interpret high order word to find amount of data to be copied 
  647.        to/from the user's address space. */
  648.     size =(request &~(IOC_INOUT | IOC_VOID)) >> 16;
  649.     
  650.     /* Zero the buffer on the stack so the user gets back something deterministic */
  651.     if ((request & IOC_OUT) && size)
  652.         bzero((Ptr)argp, size);
  653.  
  654.     ifr =(struct ifreq *)argp;
  655.     switch(request) {
  656.     
  657.     /* Non-blocking I/O */
  658.     case FIONBIO:
  659.         fNonBlocking = (Boolean) *(int *) argp;
  660.         return 0;
  661.         
  662.     /* Number of bytes on input Q */
  663.     case FIONREAD:
  664.         *(unsigned long *) argp    = Available();
  665.         return 0;
  666.         
  667.     default :
  668.         return SK_Error(EOPNOTSUPP);
  669.     }
  670. }
  671.  
  672.  
  673. /**************************************************************************/ 
  674. /**************************************************************************/ 
  675. /* CSK_INETSocketDomain members */
  676.  
  677.  
  678. /*************************************************************************** *
  679. * FUNCTION:
  680. *
  681. * CSK_INETSocketDomain::CSK_INETSocketDomain
  682. *
  683. * DESCRIPTION:
  684. *
  685. * Constructor for this class
  686. *
  687. */
  688.  
  689. CSK_INETSocketDomain::CSK_INETSocketDomain()
  690.     :    CSK_SocketDomain(AF_INET)    
  691. {
  692.     CSK_Configuration    conf;        // SKg_Config isn't yet guaranteed to work    
  693.         
  694.     fDriverState        = 1;
  695.      fResolverState        = 1;
  696.     fDrvrRefNum         = 0;
  697.     fNumExistingSockets    = 0;
  698.             
  699.     /* Allocate storage for pbs */
  700.     fLastPBUsed = 0;
  701.     fThePBArray = NULL;
  702.     
  703.     if (conf.IsDaemon()) {
  704.         if (conf.fTCPDaemon)
  705.             AEInstallEventHandler(
  706.                 'INET', 'TSTR', AEEventHandlerProcPtr(SK_TCPPossession), 0, false);
  707.         else
  708.             AEInstallEventHandler(
  709.                 'INET', 'TSTR', AEEventHandlerProcPtr(SK_UnsupportedAEVT), 0, false);
  710.         
  711.         if (conf.fUDPDaemon)
  712.             AEInstallEventHandler(
  713.                 'INET', 'USTR', AEEventHandlerProcPtr(SK_UDPPossession), 0, false);
  714.         else
  715.             AEInstallEventHandler(
  716.                 'INET', 'USTR', AEEventHandlerProcPtr(SK_UnsupportedAEVT), 0, false);
  717.     }
  718. }
  719.  
  720.  
  721. /*************************************************************************** *
  722. * FUNCTION:
  723. *
  724. * CSK_INETSocketDomain::Driver
  725. *
  726. * DESCRIPTION:
  727. *
  728. * ???
  729. *
  730. * RETURNS:
  731. *
  732. * short        -- The driver reference number (or 0 on error)
  733. *
  734. */
  735.  
  736. short CSK_INETSocketDomain::Driver()
  737. {
  738.     ParamBlockRec         pb; 
  739.  
  740.     if (fDriverState == 1) {
  741.         pb.ioParam.ioCompletion    = 0L; 
  742.         pb.ioParam.ioNamePtr     = "\p.IPP"; 
  743.         pb.ioParam.ioPermssn     = fsCurPerm;
  744.         
  745.         fDriverState             = PBOpenSync(&pb);
  746.         fDrvrRefNum             = pb.ioParam.ioRefNum; 
  747.     }
  748.     
  749.     return fDriverState ? 0 : fDrvrRefNum;
  750. }
  751.  
  752.  
  753. /*************************************************************************** *
  754. * FUNCTION:
  755. *
  756. * CSK_INETSocketDomain::Resolver
  757. *
  758. * DESCRIPTION:
  759. *
  760. * ???
  761. *
  762. * RETURNS:
  763. *
  764. * OSErr        -- The resulting resolver state
  765. *
  766. */
  767.  
  768. OSErr CSK_INETSocketDomain::Resolver()
  769. {
  770.     if (fResolverState == 1)
  771.         fResolverState = OpenResolver(nil);
  772.     
  773.     return fResolverState;
  774. }
  775.  
  776.  
  777. /*************************************************************************** *
  778. * FUNCTION:
  779. *
  780. * CSK_Socket * CSK_INETSocketDomain::socket
  781. *
  782. * DESCRIPTION:
  783. *
  784. * Create a MacTCP socket in this socket domain.
  785. *
  786. * TCP sockets provide sequenced, reliable, two-way connection
  787. * based byte streams.
  788. *
  789. * A TCP socket must be in a connected state before any data may be sent 
  790. * or received on it. A connection to another socket is created with a 
  791. * connect() call or the listen() and accept() calls. Once connected, data may 
  792. * be transferred using read() and write() calls or some variant of the send() 
  793. * and recv() calls. When a session has been completed a close() may  be
  794. * performed.
  795. *
  796. * A UDP socket supports the exchange of datagrams (connectionless, unreliable 
  797. * messages of a fixed maximum length) with correspondents named in send() calls. 
  798. * Datagrams are generally received with recv(), which returns the next
  799. * datagram with its return address.
  800. *
  801. * An fcntl() or ioctl() call can be used to enable non-blocking I/O.
  802. *
  803. * PARAMETERS:
  804. *
  805. * int            -- The type of socket to create:
  806. *
  807. *    SOCK_STREAM        to create a TCP socket
  808. *    SOCK_DGRAM        to create a UDP socket
  809. *
  810. * short            -- unused protocol
  811. *
  812. * RETURNS:
  813. *
  814. * The return value is a descriptor referencing the socket or -1
  815. * if an error occurs, in which case global variable errno is
  816. * set to one of:
  817. *
  818. *    ENOMEM                Failed to allocate memory for the socket
  819. *                         data structures.
  820. *
  821. *    ESOCKTNOSUPPORT     Type wasn't SOCK_STREAM or SOCK_DGRAM.
  822. *
  823. *    EMFILE              The socket descriptor table is full.
  824. *
  825. */
  826.  
  827. CSK_Socket * CSK_INETSocketDomain::socket(int type, short)
  828. {
  829.     CSK_INETSocket * sock = nil;
  830.     
  831.     errno = 0;
  832.  
  833.     if (!Driver())
  834.         return (CSK_Socket *) SK_Error_nil(ENETDOWN);
  835.         
  836.     switch (type)    {
  837.     case SOCK_STREAM:
  838.         sock = new CSK_TCPSocket();
  839.         break;
  840.     case SOCK_DGRAM:
  841.         sock = new CSK_UDPSocket();
  842.         break;
  843.     default:
  844.         SK_Error(ESOCKTNOSUPPORT);
  845.     }    
  846.     
  847.     if (sock && errno)    {
  848.         delete sock;
  849.         return nil;
  850.     }
  851.         
  852.     return sock;
  853. }
  854.  
  855.  
  856. /*************************************************************************** *
  857. * FUNCTION:
  858. *
  859. * CSK_INETSocketDomain::GetPB
  860. *
  861. * DESCRIPTION:
  862. *
  863. * Get a free parameter block from the collection of parameter blocks
  864. * being used by sockets in this domain.
  865. *
  866. * RETURNS:
  867. *
  868. * CSK_AnnotatedPB *            -- The free parameter block object
  869. *
  870. * NOTES:
  871. *
  872. * If all parameter blocks are in use, then this routine will loop until 
  873. * one becomes available (possibly forever, as I am now finding out).
  874. *
  875. */
  876.  
  877. CSK_AnnotatedPB * CSK_INETSocketDomain::GetPB()
  878. {
  879.     CSK_AnnotatedPB    * curPB;
  880.     Boolean once_around = FALSE;
  881.     long final_tick;
  882.     
  883.     /* Error check */
  884.     ASSERT(fThePBArray != NULL);
  885.     
  886.     /* Try to locate a free parameter block */
  887.     do {
  888.         if (++fLastPBUsed == SKk_Num_PBs) {
  889.             // If already went once around without finding anything, then we give
  890.             // up some time to the OS, in the hope that some parameter block will
  891.             // be freed upon a completion
  892.             if (once_around) SystemTask();
  893.             
  894.             once_around = TRUE;
  895.             fLastPBUsed = 0;
  896.             }
  897.         
  898.         curPB = fThePBArray + fLastPBUsed;
  899.     } while (curPB->Busy());
  900.     
  901.     // Return block
  902.     return curPB;
  903. }
  904.  
  905.  
  906. /*************************************************************************** *
  907. * FUNCTION:
  908. *
  909. * CSK_INETSocketDomain::OpenSocket
  910. *
  911. * DESCRIPTION:
  912. *
  913. * ???
  914. *
  915. */
  916.  
  917. void CSK_INETSocketDomain::OpenSocket()
  918. {
  919.     /* Allocate PB array if this is first socket to be opened */
  920.     if (fThePBArray == NULL) {
  921.         fThePBArray = new CSK_AnnotatedPB[SKk_Num_PBs];
  922.         if (fThePBArray == NULL) {
  923.             errno = ENOMEM;
  924.             return;
  925.         }
  926.     }
  927.     
  928.     /* Count this socket */    
  929.     fNumExistingSockets++;
  930. }
  931.  
  932.  
  933. /*************************************************************************** *
  934. * FUNCTION:
  935. *
  936. * CSK_INETSocketDomain::CloseSocket
  937. *
  938. * DESCRIPTION:
  939. *
  940. * ???
  941. *
  942. */
  943.  
  944. void CSK_INETSocketDomain::CloseSocket()
  945. {
  946.     /* Decrement socket counter */
  947.     fNumExistingSockets--;
  948.     
  949.     /* If no sockets left, then deallocate PB array */
  950.     if (fNumExistingSockets == 0) {
  951.         delete [] fThePBArray;
  952.         fThePBArray = NULL;
  953.     }
  954.  }
  955.  
  956.  
  957. /* end of SK_INET.cc */
  958.